package hadoop.hdfs.demo;

import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.io.LongWritable;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.io.compress.DefaultCodec;
import org.apache.hadoop.mapreduce.Job;
import org.apache.hadoop.mapreduce.Mapper;
import org.apache.hadoop.mapreduce.Reducer;
import org.apache.hadoop.mapreduce.lib.input.FileInputFormat;
import org.apache.hadoop.mapreduce.lib.output.FileOutputFormat;

import java.io.IOException;

/**
 * @author qiss
 * @create 2018-02-12 17:20
 **/
public class BeanCountRunner {
    public static void main(String[] args) throws Exception{
        Job job = Job.getInstance(new Configuration());

        job.setJarByClass(BeanCountRunner.class);

        job.setMapperClass(BeanMapper.class);
        job.setReducerClass(BeanReduce.class);

        job.setMapOutputKeyClass(BeanComparable.class);
        job.setMapOutputValueClass(Text.class);

        job.setOutputKeyClass(Text.class);
        job.setOutputValueClass(BeanComparable.class);

        job.setPartitionerClass(ProvincePartitioner.class);

        FileInputFormat.setInputPaths(job,new Path(args[0]));

        //Reduce输出压缩，也可以通过xml参数配置
        FileOutputFormat.setCompressOutput(job,true);
        FileOutputFormat.setOutputCompressorClass(job, DefaultCodec.class);
        FileOutputFormat.setOutputPath(job,new Path(args[1]));

        job.waitForCompletion(true);
    }

    static class BeanMapper extends Mapper<LongWritable,Text,BeanComparable,Text>{

        /**
         * 在map任务初始化的时候调用一次，可以加入一些数据，做到在map端进行join,避免数据倾斜，例如加载商品数据到内存中
         * @param context
         * @throws IOException
         * @throws InterruptedException
         */
        @Override
        protected void setup(Context context) throws IOException, InterruptedException {
            super.setup(context);
        }

        @Override
        protected void map(LongWritable key, Text value, Context context) throws IOException, InterruptedException {
            String[] fields = value.toString().split(" ");
            String phoneNum = fields[0];
            int sum1 = Integer.parseInt(fields[1]);
            int sum2 = Integer.parseInt(fields[2]);
            BeanComparable beanComparable = new BeanComparable(sum1, sum2);

            context.write(beanComparable,new Text(phoneNum));
        }
    }

    static class BeanReduce extends Reducer<BeanComparable,Text,Text,BeanComparable>{
        @Override
        protected void reduce(BeanComparable key, Iterable<Text> phoneNum, Context context) throws IOException, InterruptedException {
            Text phoneNbr = phoneNum.iterator().next();
            context.write(phoneNbr,key);
        }
    }
}
